package com.ce.framework.datamaintain.implement;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.beanutils.PropertyUtils;
import org.apache.poi2.hssf.usermodel.HSSFCell;
import org.apache.poi2.hssf.usermodel.HSSFRow;
import org.apache.poi2.hssf.usermodel.HSSFSheet;
import org.apache.poi2.hssf.usermodel.HSSFWorkbook;
import org.apache.poi2.hssf.util.Region;

import com.ce.framework.datamaintain.dao.IBaseDao;
import com.ce.framework.datamaintain.logic.IBaseLogic;
import com.ce.framework.datamaintain.logic.ISQLMapper;
import com.ce.framework.datamaintain.logic.ISearchCondition;
import com.ce.framework.datamaintain.logic.ISearchInfo;
import com.ce.framework.datamaintain.logic.SQLSearchCondition;
import com.ce.framework.exception.AppException;
import com.ce.framework.exception.DaoException;
import com.ce.framework.util.DateUtil;
import com.ce.framework.util.LogUtil;
import com.ce.framework.util.StringUtil;
import com.ce.tag.ExcelUtil;
import com.ce.util.DbUtil;

/**
 * 嫦娥软件有限公司 版权所有 2013
 * 创建人： andy
 * 创建时间： 2013-9-11 上午10:48:53
 * 功能描述：基类逻辑层的实现类
 * ==================================
 * 修改历史
 * 修改人        修改时间      修改位置（函数名）
 *
 * ==================================
 */
public class BaseLogic implements IBaseLogic {
	
	protected IBaseDao basedao;
	
	public IBaseDao getBasedao() {
		return basedao;
	}

	public void setBasedao(IBaseDao basedao) {
		this.basedao = basedao;
	}

	public void addPo(Object po) throws AppException {
		this.basedao.addPo(po);
	}

	public void deletePos(List<?> delList) throws AppException {
		this.basedao.deletePos(delList);
	}

	public void deleteSearchHQL(String hql) throws AppException {
		this.basedao.deleteSearchHQL(hql);
	}

	public Object getPOByPk(String poClassName, String pk) throws AppException {
		return this.basedao.getPo(poClassName, pk);
	}

	public List<?> getSearchResult(ISearchCondition searchCondition)
			throws AppException {
		List<?> datas = null;
		if(searchCondition != null){
			datas = this.basedao.search(searchCondition);
		}
		return datas;
	}

	public List<?> getSearchResult(ISearchInfo searchInfo)
			throws AppException {
		if(this.basedao==null){
			throw new AppException("invoke "+this.getClass().getName()+" class's getSearchResult method not init searchDAO attribute.");
		}
		//得到分页结果信息。
		this.basedao.getDivideResultInfo(searchInfo);
		//得到查询结查数据.
		List<?> datas=this.basedao.search(searchInfo);
		return datas;
	}

	public int deleteLogic(Object po, String[] ids, String delField,String childPoName)
			throws AppException {
		return this.basedao.deleteLogic(po.getClass().getName(), ids, delField,childPoName);
	}

	public void updatePo(Object po) throws AppException {
		this.basedao.updatePo(po);
	}

	public void updatePos(Collection<?> pos) throws AppException {
		this.basedao.updatePos(pos);
	}

	public void addPo(Object po, List<?> addChildList) throws AppException {
		this.basedao.addPo(po);
		this.basedao.addPos(addChildList);
	}

	public void updatePo(Object po, List<?> addChildList, List<?> modifyChildList)
			throws AppException {
		updatePo(po,addChildList,modifyChildList,null);
	}

	public void updatePo(Object po, List<?> addChildList, List<?> modifyChildList, List<?> deleteChildList)
			throws AppException {
		this.basedao.updatePo(po);
		this.basedao.deletePos(deleteChildList);
		this.basedao.addPos(addChildList);
		this.basedao.updatePos(modifyChildList);
	}

	public List<?> searchByHql(String hql) throws AppException {
		try{
			return this.basedao.findByHql(hql);	
		}catch(DaoException e){
			throw new AppException("指定的("+hql+")未能查询到相应数据列表",e);
		}
	}

	public List<?> searchByHql(String hql,Object[] params) throws AppException {
		try{
			return this.basedao.findByHql(hql,params);	
		}catch(DaoException e){
			throw new AppException("指定的("+hql+")未能查询到相应数据列表",e);
		}
	}

	public List<?> executeSQLQuery(String sql, ISQLMapper mapper) {
		return DbUtil.executeSqlQuery(sql, mapper);
	}
	
	public List<?> executePreparedSQLQuery(SQLSearchCondition condition, ISQLMapper mapper) {
		try {
			return this.basedao.queryData(condition, mapper);
		} catch (AppException e) {
			LogUtil.logError(e);
		}
		return null;
	}

	public int getCntByHQL(String hql) throws AppException{
		List<?> list = this.searchByHql(hql);
		if(list!=null&&list.size()>0)
			return list.size();
		else
		    return 0;
	}
	public HSSFWorkbook genExcel(final ISearchCondition search,File f) throws FileNotFoundException, IOException, AppException {
		return genExcel(search, f, null);
	}
	public HSSFWorkbook genExcel(final Object search,File f,List<?> data) throws FileNotFoundException, IOException, AppException {
		HSSFWorkbook wb = null;
		FileInputStream in = new FileInputStream(f);
		wb = new HSSFWorkbook(in);
		for(int i=0;i<wb.getNumberOfSheets();i++){
			genExcel(search, wb.getSheetAt(i), data);
		}
		in.close();
		return wb;
	}
	public void genExcel(final Object search,final HSSFSheet sheet,List<?> data) throws FileNotFoundException, IOException, AppException {
		final ArrayList<HSSFRow> contRow = new ArrayList<HSSFRow>();
		HSSFRow row = null,trow=null;
		HSSFCell cell = null,tcell=null;
		String str = null;
		Pattern pat1 = Pattern.compile("#\\{([^\\}]+)\\}");
		Pattern pat2 = Pattern.compile("\\$\\{([^\\}]+)\\}");
		Pattern pat3 = Pattern.compile("%\\{([^\\}]+)\\}");
		Matcher mat = null;
		int mbStart = 9999999,mbEnd = 0;
		for(int i=0;i<=sheet.getLastRowNum();i++){
			row = sheet.getRow(i);
			if(row==null){
				continue;
			}
			boolean isMb = false;
			for(int j=0;j<=row.getLastCellNum();j++){
				cell = row.getCell((short) j);
				str = cell==null?null:cell.getCellType()==HSSFCell.CELL_TYPE_NUMERIC?""+cell.getNumericCellValue():cell.getStringCellValue();
				if(StringUtil.isNotBlank(str)){
					mat = pat1.matcher(str);
					while(mat.find()){//表中需要使用searchCondition中属性替换的内容
						String name = mat.group(1);
						Object val = "";
						try {//将属性名称解析为searchCondition中的属性值
							val = PropertyUtils.getProperty(search, name);
						} catch (Exception e) {
							LogUtil.logError(e);
						}
						String strval = val==null?"":val.toString();
						str = str.replace("#{"+name+"}", strval);
					}
					cell.setEncoding(HSSFCell.ENCODING_UTF_16);
					cell.setCellValue(str);
					mat = pat2.matcher(str);
					if(mat.find()&&!isMb){//数据区
						isMb = true;
					}
				}
			}
			if(isMb){//指定数据区的起止行号
				mbStart = Math.min(mbStart, row.getRowNum());
				mbEnd = Math.max(mbEnd, row.getRowNum());
			}
		}
		for(int i=mbStart;i<=mbEnd;i++){
			contRow.add(sheet.getRow(i));
		}
		final int endRowNum = sheet.getLastRowNum();
		final List<String> res = new ArrayList<String>();
		if(search instanceof ISearchCondition && data==null){//使用SQL从数据库直接查询出数据
			final ISearchCondition srh = (ISearchCondition) search;
			basedao.queryData(srh,new ISQLMapper() {
				public Object fromSQLQuery(ResultSet rs, int num) {
					dealDataRow(sheet, contRow, res, num, srh.fromSQLQuery(rs, num));
					return null;
				}
			});
		}
		else{//使用传递过来的列表组织数据
			int num = 0;//从0开始，在生成行号时已经做了+1处理
			for(Object obj:data){
				//处理模板行
				dealDataRow(sheet, contRow, res, num++, obj);
			}
		}
		if(res.isEmpty()){//如果未查出数据，则添加空行，然后再清除模板数据
			for(int i=0;i<contRow.size();i++){//处理模板行
				row = sheet.createRow(sheet.getLastRowNum()+1);
				trow = contRow.get(i);
				for(int j=0;j<=trow.getLastCellNum();j++){//处理行中的单元格
					tcell = trow.getCell((short) j);
					if(tcell==null)continue;
					cell = row.createCell((short) j);
					cell.setCellStyle(tcell.getCellStyle());
				}
			}
		}
		//将模板区及表尾区向下移动到底部
		sheet.shiftRows(mbStart, endRowNum, sheet.getLastRowNum()-mbStart+1,true,true);
		//将数据区向上移动
		sheet.shiftRows(endRowNum+1, sheet.getLastRowNum(), mbStart-endRowNum-1,true,true);
		int rowCnt = sheet.getLastRowNum();
		for(int i=mbEnd;i>=mbStart;i--){//删除模板行
			sheet.removeRow(sheet.getRow(rowCnt-(endRowNum-i)));
		}
		//将表尾区向上移动
		sheet.shiftRows(sheet.getLastRowNum()-(endRowNum-mbEnd)+1, sheet.getLastRowNum(), -(mbEnd-mbStart+1),true,true);
		for(int i=0;i<=sheet.getLastRowNum();i++){//计算完成后再替换页脚，用于显示合计等内容
			row = sheet.getRow(i);
			if(row==null){
				continue;
			}
			for(int j=0;j<=row.getLastCellNum();j++){
				cell = row.getCell((short) j);
				str = null;
				try {
					str = (cell==null||cell.getCellType()!=HSSFCell.CELL_TYPE_STRING)?null:cell.getStringCellValue();
				} catch (Exception e1) {
					e1.printStackTrace();
				}
				if(StringUtil.isNotBlank(str)){
					mat = pat3.matcher(str);
					while(mat.find()){//表中需要使用searchCondition中属性替换的内容
						String name = mat.group(1);
						Object val = "";
						try {//将属性名称解析为searchCondition中的属性值
							val = PropertyUtils.getProperty(search, name);
						} catch (Exception e) {
							LogUtil.logError(e);
						}
						val = val==null?"":val;
						str = str.replace("%{"+name+"}", val.toString());
					}
					cell.setEncoding(HSSFCell.ENCODING_UTF_16);
					if(StringUtil.isFloat(str)){
						cell.setCellValue(Double.parseDouble(str));
					}
					else{
						cell.setCellValue(str);
					}
				}
			}
		}
	}

	/** 将obj中的数据填充到Excel文件中 */
	protected void dealDataRow(final HSSFSheet sheet, final ArrayList<HSSFRow> contRow, final List<String> res,
			int num, Object obj) {
		Pattern mypat = Pattern.compile("\\$\\{([^\\}]+)\\}");
		Matcher mat = null;
		HSSFRow row = null,trow=null;
		HSSFCell cell = null,tcell=null;
		String str = null;
		for(int i=0;i<contRow.size();i++){//处理模板行
			row = sheet.createRow(sheet.getLastRowNum()+1);
//						sheet.shiftRows(sheet.getLastRowNum()-tailRows, sheet.getLastRowNum(), 1,true,true);
//						row = sheet.createRow(sheet.getLastRowNum()-tailRows-1);
			trow = contRow.get(i);
			if(trow.getHeightInPoints()>20){
				row.setHeight(trow.getHeight());
			}
			for(int j=0;j<=trow.getLastCellNum();j++){//处理行中的单元格
				cell = row.createCell((short) j);
				tcell = trow.getCell((short) j);
				if(tcell==null)continue;
				Region reg = ExcelUtil.getMergedRegion(sheet, trow.getRowNum(), j);
				if(reg!=null){
					sheet.addMergedRegion(new Region(reg.getRowFrom()+row.getRowNum()-trow.getRowNum(),reg.getColumnFrom(),reg.getRowTo()+row.getRowNum()-trow.getRowNum(),reg.getColumnTo()));
				}
				cell.setCellStyle(tcell.getCellStyle());
				cell.setEncoding(HSSFCell.ENCODING_UTF_16);
				str = tcell.getStringCellValue();
				if(str==null)continue;
				str = str.trim();
				mat = mypat.matcher(str);
				boolean isNum=false;
				Date cellDate = null;
				while(mat.find()){//表中需要使用searchCondition中属性替换的内容
					String name = mat.group(1);
					String value = "";
					Object tmpo = null;
					if("index".equals(name)){
						value = ""+(num+1);
					}
					else{
						try {//将属性名称解析为searchCondition中的属性值
							tmpo = PropertyUtils.getProperty(obj, name);
							value = tmpo==null?"":tmpo.toString();
						} catch (Exception e) {
							LogUtil.logError(e);
						}
					}
					value = value==null?"":value;
					if(("${"+name+"}").equals(str)){
						String patt = ",byte,double,float,int,long,short,";
						if(tmpo!=null&&(patt.contains(tmpo.getClass().getName()))||tmpo instanceof Number){
							isNum=true;
						}
					}
					if(tmpo!=null && tmpo instanceof Date && ("${"+name+"}").equals(str)){
						cellDate = (Date) tmpo;
					}
					str = str.replace("${"+name+"}", value);
				}
				if(isNum||tcell.getCellType()==HSSFCell.CELL_TYPE_NUMERIC){
					try {
						cell.setCellValue(Double.parseDouble(str));
					} catch (NumberFormatException e) {
						cell.setCellValue(str);
					}
				}
				else if(cellDate!=null){
					cell.setCellValue(cellDate);
				}
				else{
					cell.setCellValue(str);
				}
			}
		}
		if(res.isEmpty())res.add("1");//如果有数据，将res插入一条记录，以便于下边分析
	}
	

	
}
